#ifndef NET_BUFFER_H
#define NET_BUFFER_H

#include <stdexcept>

class NetBuffer
{
public:
    static NetBuffer *ref (NetBuffer *buffer)
    {
        SF_ASSERT(buffer->_ref);
        ++buffer->_ref;
        return buffer;
    }

    static void unref (NetBuffer *buffer)
    {
        SF_ASSERT(buffer->_ref);
        if (--buffer->_ref == 0)
        {
            delete buffer;
        }
    }

    static NetBuffer *newBuffer(size_t size = 1)
    {
        return new NetBuffer(size);
    }

    /**
     * @brief packBuffer
     * @param tmp [in] 传入的一个临时数组，然后把数组打包程NetBuffer
     * @param ptr [in] 指针buffer位置
     * @param size [in] 指针对应数据长度
     * @return 返回封装的NetBuffer地址
     * @details 给引用指针使用
     * @example char tmp[sizeof(NetBuffer)];
     *          NetBuffer::packBuffer(tmp, pointer, size);
     */
    static NetBuffer *packBuffer(char *tmp, uint8_t *ptr, size_t size)
    {
        reinterpret_cast<NetBuffer *> (tmp)->_buffer     = ptr;
        reinterpret_cast<NetBuffer *> (tmp)->_bufferSize = 0;
        reinterpret_cast<NetBuffer *> (tmp)->_dataSize   = size;
        reinterpret_cast<NetBuffer *> (tmp)->_ref        = 0; // 表明不能被ref使用
        return reinterpret_cast<NetBuffer *> (tmp);
    }

    void realloc(size_t size)
    {
        _bufferSize += size;
        _buffer      = static_cast<unsigned char *> (::realloc(_buffer, _bufferSize));
        if (!_buffer)
        {
            throw std::runtime_error("net buffer realloc no memery");
        }
    }

    void append(uint8_t *data, size_t size)
    {
        size_t newSize = size + _dataSize;
        if (newSize > _bufferSize)
        {
            size_t inc = (newSize > (_bufferSize + size)) ? newSize - _bufferSize
                                                          : size;
            realloc(inc + 1);
        }

        memcpy(&(_buffer[_dataSize]), data, size);
        _dataSize           += size;
        _buffer[_dataSize]   = 0;
    }

    uint8_t *buffer()
    {
        return _buffer;
    }

    size_t size()
    {
        return _dataSize;
    }
    void setSize(size_t s)
    {
        _dataSize = s;
    }
private:
    NetBuffer(size_t size)
        : _buffer(static_cast<uint8_t *> (malloc(size)))
        , _bufferSize(size), _dataSize(0), _ref(1)
    {
        if (!_buffer)
        {
            throw std::runtime_error("net buffer malloc no memery");
        }
    }
//    NetBuffer(uint8_t *ptr, size_t size)
//        : _buffer(ptr)
//        , _bufferSize(0), _dataSize(size), _ref(0)
//    {
//    }
    ~NetBuffer()
    {
        //GEN_Printf(LOG_DEBUG, "free buffer");
        if (_buffer)
        {
            ::free(_buffer);
        }
    }
    NetBuffer(NetBuffer &);
    NetBuffer &operator=(NetBuffer &);

    uint8_t *_buffer;
    size_t  _bufferSize;
    size_t  _dataSize;
    /**
     * @brief _ref ref初始化为0表示当前buffer仅仅只是引用其他的指针,不能别的地方引用
     * ref初始化为1，表示这个buffer才可以使用ref/unref
     */
    size_t  _ref;
};

#endif // NET_BUFFER_H
